Purpose

As someone who cares about personal finance, I find that one of the most important steps towards financial well being is understanding your spending habits. This document goes over my typical analysis process for monitoring my own finances and includes a csv file of what my raw data input is. However, I have changed significant portions of the data to anonymize the data.

Yearly Spending Comparison

The first thing I like to look at is what my yearly spending has been historically and where I am in regards to my yearly budget. The below graph shows this high level comparison so that I can get an understanding over a long period of time what my spending habits look like.

Monthly Spending Year Over Year Comparison

I next like to dig down one more step to see how my monthly spending compares to the same month in years past. This tends to be much more variable as somewhat large purchases are not made in the same month every year (car maintenance, doctor visits, paying taxes early); however, it still gives me an idea of where my spending has been for the past month and any anomalies typically get explained in the graph following this.

Monthly Spending Category Breakdown

The next visualization gives a breakdown of what categories I spent money in over the past 15 months. This allows me to identify any atypical spending habits and see what categories my money has been going to.

Spending Year To Month Comparions

Since taking snapshots of individual months can give high amounts of variability with smaller subcategories (like music, taxes, and gifts), the next visualization is intended to aggregate those number over similar time frames to give more meaningful comparisons. Since this analysis runs through August, the graphs below add up all the spending from January through August of 2019, 2020, and 2021 and compare them to see if I’m spending more in a certain category from a similar time frame in the past.

Subcategory Budget Monitoring

At the beginning of the year, I typically create a budget for some of my high spending subcategories. This allows me to gain a better understanding of where my spending habits are in comparison to my spending goals.

Utilities

Since utilities typically have some predictability to them, I like to preform a year over year month comparison. I start with electric, which is seasonal since my A/C and heat are both electric. In addition, I performed a linear regression to make a prediction for what my electric should be for each month using previous year’s costs to see how much the actual cost varies from that.

For water and sewage, these two are typically tied together and I have graphed them side by side below. For sewage, they fix the price by 1000 gallons and it typically falls between 1000 and 2000 so they charge me for 1 or 2 “Units” of sewage, which is why the graph is so step oriented.

LS0tDQp0aXRsZTogIk1vbnRobHkgU3BlbmRpbmcgQW5hbHlzaXMiDQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOg0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KLS0tDQojIFB1cnBvc2UNCkFzIHNvbWVvbmUgd2hvIGNhcmVzIGFib3V0IHBlcnNvbmFsIGZpbmFuY2UsIEkgZmluZCB0aGF0IG9uZSBvZiB0aGUgbW9zdCBpbXBvcnRhbnQgc3RlcHMgdG93YXJkcyBmaW5hbmNpYWwgd2VsbCBiZWluZyBpcyB1bmRlcnN0YW5kaW5nIHlvdXIgc3BlbmRpbmcgaGFiaXRzLiAgVGhpcyBkb2N1bWVudCBnb2VzIG92ZXIgbXkgdHlwaWNhbCBhbmFseXNpcyBwcm9jZXNzIGZvciBtb25pdG9yaW5nIG15IG93biBmaW5hbmNlcyBhbmQgaW5jbHVkZXMgYSBjc3YgZmlsZSBvZiB3aGF0IG15IHJhdyBkYXRhIGlucHV0IGlzLiAgSG93ZXZlciwgSSBoYXZlIGNoYW5nZWQgc2lnbmlmaWNhbnQgcG9ydGlvbnMgb2YgdGhlIGRhdGEgdG8gYW5vbnltaXplIHRoZSBkYXRhLg0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLndpZHRoPTksIGVjaG89RkFMU0V9DQojTG9hZCBSZWxldmFudCBMaWJyYXJpZXMNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoem9vKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoc3RyaW5ncikNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KG1vZGVscikNCmxpYnJhcnkoZm9ybWF0dGFibGUpDQpgYGANCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcud2lkdGg9OSwgZWNobz1GQUxTRX0NCiNEZWZpbmUgR2xvYmFsIFZhcmlhYmxlcw0KcmVwb3J0X21vbnRoIDwtIGFzLnllYXJtb24oIkF1Z3VzdCAyMDIxIikgI0xhc3QgZnVsbCBtb250aCBJIGhhdmUgZGF0YSBmb3INCmBgYA0KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy53aWR0aD05LCBlY2hvPUZBTFNFfQ0KI1NldCB1cCBhbmQgY2xlYW4gcHJpbWFyeSBkYXRhIGZyYW1lDQpkZiA8LSByZWFkLmNzdigiRmluYW5jZXMgQ29tYmluZWQuY3N2IiwgZmlsZUVuY29kaW5nID0gIlVURi04LUJPTSIpDQoNCiMxOiBSZW1vdmUgdGhlICIkIiBpbiB0aGUgYW1vdW50IGNvbHVtbiBhbmQgY2hhbmdlIGl0IHRvIG51bWVyaWMNCmRmJEFtb3VudCA8LSBnc3ViKCJbJF0iLCIiLGRmJEFtb3VudCkNCmRmJEFtb3VudCA8LSBhcy5udW1lcmljKGRmJEFtb3VudCkNCg0KIzI6IENoYW5nZSBkYXRlIHRvIGRhdGUgZm9ybWF0IGFuZCBhZGQgWWVhck1vbiwgWWVhciwgYW5kIE1vbnRoIGNvbHVtbnMNCmRmJFRyYW5zYWN0aW9uLkRhdGUgPC0gbWR5KGRmJFRyYW5zYWN0aW9uLkRhdGUpDQpkZiA8LSBtdXRhdGUoZGYsIlllYXJNb24iID0gYXMueWVhcm1vbihUcmFuc2FjdGlvbi5EYXRlKSkgJT4lDQogIG11dGF0ZSgiWWVhciIgPSBhcy5mYWN0b3IoeWVhcihUcmFuc2FjdGlvbi5EYXRlKSkpICU+JQ0KICBtdXRhdGUoIk1vbnRoIiA9IG1vbnRoKFRyYW5zYWN0aW9uLkRhdGUsIGxhYmVsID0gVFJVRSkpICU+JQ0KICBtdXRhdGUoIk1vbnRoLk51bWJlciIgPSBtb250aChUcmFuc2FjdGlvbi5EYXRlKSkNCg0KI0ZpbHRlciBvdXQgdGhlIGZ1dHVyZSBwdXJjaGFzZXMgYmVjYXVzZSB0aGUgYW5udWFsaXplZCBvbmVzIGFyZSBvbiB0aGVyZSB0aHJvdWdoIHRoZSBlbmQgb2YgdGhlIHllYXIuDQpkZiA8LSBmaWx0ZXIoZGYsIFllYXJNb24gPD0gcmVwb3J0X21vbnRoKQ0KYGBgDQoNCiMjIFllYXJseSBTcGVuZGluZyBDb21wYXJpc29uDQpUaGUgZmlyc3QgdGhpbmcgSSBsaWtlIHRvIGxvb2sgYXQgaXMgd2hhdCBteSB5ZWFybHkgc3BlbmRpbmcgaGFzIGJlZW4gaGlzdG9yaWNhbGx5IGFuZCB3aGVyZSBJIGFtIGluIHJlZ2FyZHMgdG8gbXkgeWVhcmx5IGJ1ZGdldC4gIFRoZSBiZWxvdyBncmFwaCBzaG93cyB0aGlzIGhpZ2ggbGV2ZWwgY29tcGFyaXNvbiBzbyB0aGF0IEkgY2FuIGdldCBhbiB1bmRlcnN0YW5kaW5nIG92ZXIgYSBsb25nIHBlcmlvZCBvZiB0aW1lIHdoYXQgbXkgc3BlbmRpbmcgaGFiaXRzIGxvb2sgbGlrZS4NCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy53aWR0aD05LCBlY2hvPUZBTFNFfQ0KI1N0YXJ0IEdyYXBoIDE6IEhpc3Rvcnkgb2YgWWVhcmx5IFNwZW5kaW5nIGFuZCB3aGVyZSBidWRnZXQgY3VycmVudGx5IHN0YW5kcw0KI0RlZmluZSBCdWRnZXQNCmJ1ZGdldCA8LSBkYXRhLmZyYW1lKFllYXIgPSBhcy5mYWN0b3IoMjAyMSksDQogICAgICAgICAgICAgICAgICAgICBUb3RhbF9ZZWFybHlfU3BlbmRpbmcgPSAyNTAwMCwNCiAgICAgICAgICAgICAgICAgICAgIENhdGVnb3J5ID0gIkJ1ZGdldCIpDQoNCiNHZXQgcHJldmlvdXMgeWVhcidzIHNwZW5kaW5nDQpkZjEgPC0gZGYgJT4lDQogIGdyb3VwX2J5KFllYXIpICU+JQ0KICBzdW1tYXJpc2UoIlRvdGFsX1llYXJseV9TcGVuZGluZyIgPSBzdW0oQW1vdW50KSkgJT4lDQogIG11dGF0ZSgiQ2F0ZWdvcnkiID0gIlNwZW50IikNCg0KcGxvdF9seSgpICU+JQ0KDQogIGFkZF9iYXJzKGRhdGEgPSBidWRnZXQsDQogICAgICAgICB4ID0gflllYXIsDQogICAgICAgICB5ID0gflRvdGFsX1llYXJseV9TcGVuZGluZywNCiAgICAgICAgIGNvbG9yID0gfkNhdGVnb3J5LA0KICAgICAgICAgdHlwZSA9ICJiYXIiLA0KICAgICAgICAgdGV4dCA9IHBhc3RlMCgiJCIsYXMuY2hhcmFjdGVyKGFjY291bnRpbmcoYnVkZ2V0JFRvdGFsX1llYXJseV9TcGVuZGluZykpKSwNCiAgICAgICAgIHRleHRmb250ID0gbGlzdChjb2xvciA9ICcjMDAwMDAwJyksDQogICAgICAgICB0ZXh0cG9zaXRpb24gPSAiYXV0byIsIA0KICAgICAgICAgbWFya2VyID0gbGlzdChjb2xvciA9ICIjYmFmZmNkIiwNCiAgICAgICAgICAgICAgICAgICAgICAgbGluZSA9IGxpc3Qod2lkdGggPSAxLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAncmdiKDAsIDAsIDApJykpLA0KICAgICAgICAgaG92ZXJpbmZvID0gInRleHQiLCAjVGhpcyBzdG9wcyB0aGUgZGVmYXVsdCBob3ZlciBvdmVyDQogICAgICAgICBob3ZlcnRleHQgPSBwYXN0ZTAoIlllYXI6ICIsIGJ1ZGdldCRZZWFyLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8YnI+QW1vdW50OiAkIiwgYWNjb3VudGluZyhidWRnZXQkVG90YWxfWWVhcmx5X1NwZW5kaW5nKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGJyPkNhdGVnb3J5OiAiLCBidWRnZXQkQ2F0ZWdvcnkpDQogICAgICAgICApICU+JQ0KICANCiAgYWRkX2JhcnMoZGF0YSA9IGRmMSwNCiAgICAgICAgIHggPSB+WWVhciwNCiAgICAgICAgIHkgPSB+VG90YWxfWWVhcmx5X1NwZW5kaW5nLA0KICAgICAgICAgY29sb3IgPSB+Q2F0ZWdvcnksDQogICAgICAgICB0eXBlID0gImJhciIsDQogICAgICAgICB0ZXh0ID0gcGFzdGUwKCIkIixhcy5jaGFyYWN0ZXIoYWNjb3VudGluZyhkZjEkVG90YWxfWWVhcmx5X1NwZW5kaW5nKSkpLA0KICAgICAgICAgdGV4dGZvbnQgPSBsaXN0KGNvbG9yID0gJyMwMDAwMDAnKSwNCiAgICAgICAgIHRleHRwb3NpdGlvbiA9ICJhdXRvIiwgDQogICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gIiMyYmM0MzUiLA0KICAgICAgICAgICAgICAgICAgICAgICBsaW5lID0gbGlzdCh3aWR0aCA9IDEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICdyZ2IoMCwgMCwgMCknKSksDQogICAgICAgICBob3ZlcmluZm8gPSAidGV4dCIsICNUaGlzIHN0b3BzIHRoZSBkZWZhdWx0IGhvdmVyIG92ZXINCiAgICAgICAgIGhvdmVydGV4dCA9IHBhc3RlMCgiWWVhcjogIiwgZGYxJFllYXIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxicj5BbW91bnQ6ICQiLCBhY2NvdW50aW5nKGRmMSRUb3RhbF9ZZWFybHlfU3BlbmRpbmcpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8YnI+Q2F0ZWdvcnk6ICIsIGRmMSRDYXRlZ29yeSkNCiAgICAgICAgICkgJT4lDQogIA0KIGxheW91dChiYXJtb2RlID0gJ292ZXJsYXknLA0KICAgICAgICB0aXRsZSA9ICJZZWFybHkgU3BlbmRpbmcgYW5kIEJ1ZGdldCIsDQogICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJZZWFybHkgU3BlbmRpbmcgKCQpIiksDQogICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJZZWFyIiwNCiAgICAgICAgICAgICAgICAgICAgIGNhdGVnb3J5b3JkZXIgPSAiY2F0ZWdvcnkgYXNjZW5kaW5nIiksDQogICAgICAgIHNob3dsZWdlbmQgPSBGQUxTRSkNCmBgYA0KDQojIyBNb250aGx5IFNwZW5kaW5nIFllYXIgT3ZlciBZZWFyIENvbXBhcmlzb24NCg0KSSBuZXh0IGxpa2UgdG8gZGlnIGRvd24gb25lIG1vcmUgc3RlcCB0byBzZWUgaG93IG15IG1vbnRobHkgc3BlbmRpbmcgY29tcGFyZXMgdG8gdGhlIHNhbWUgbW9udGggaW4geWVhcnMgcGFzdC4gIFRoaXMgdGVuZHMgdG8gYmUgbXVjaCBtb3JlIHZhcmlhYmxlIGFzIHNvbWV3aGF0IGxhcmdlIHB1cmNoYXNlcyBhcmUgbm90IG1hZGUgaW4gdGhlIHNhbWUgbW9udGggZXZlcnkgeWVhciAoY2FyIG1haW50ZW5hbmNlLCBkb2N0b3IgdmlzaXRzLCBwYXlpbmcgdGF4ZXMgZWFybHkpOyBob3dldmVyLCBpdCBzdGlsbCBnaXZlcyBtZSBhbiBpZGVhIG9mIHdoZXJlIG15IHNwZW5kaW5nIGhhcyBiZWVuIGZvciB0aGUgcGFzdCBtb250aCBhbmQgYW55IGFub21hbGllcyB0eXBpY2FsbHkgZ2V0IGV4cGxhaW5lZCBpbiB0aGUgZ3JhcGggZm9sbG93aW5nIHRoaXMuDQoNCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcud2lkdGg9OSwgZWNobz1GQUxTRX0NCmRmMiA8LSBkZiAlPiUNCiAgZ3JvdXBfYnkoWWVhck1vbixZZWFyLE1vbnRoKSAlPiUNCiAgc3VtbWFyaXplKCJBbW91bnQiID0gc3VtKEFtb3VudCksIC5ncm91cHMgPSAiZHJvcF9sYXN0IikgJT4lDQogIHVuZ3JvdXAoKQ0KDQpwbG90X2x5KGRmMiwNCiAgICAgICAgeCA9IH5Nb250aCwNCiAgICAgICAgeSA9IH5BbW91bnQsDQogICAgICAgIGNvbG9yID0gflllYXIsDQogICAgICAgIHR5cGUgPSAic2NhdHRlciIsDQogICAgICAgIG1vZGUgPSAibGluZXMrbWFya2VycyIsDQogICAgICAgIGhvdmVyaW5mbyA9ICJ0ZXh0IiwNCiAgICAgICAgaG92ZXJ0ZXh0ID0gcGFzdGUwKCJBbW91bnQ6ICQiLCBhY2NvdW50aW5nKGRmMiRBbW91bnQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxicj5ZZWFyL01vbnRoOiAiLCBkZjIkWWVhck1vbikNCiAgICAgICAgKSAlPiUNCiAgDQogIGxheW91dCh0aXRsZSA9ICJNb250aGx5IFNwZW5kaW5nIENvbXBhcmluZyBZZWFyIE92ZXIgWWVhciIsDQogICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiQW1vdW50ICgkKSIpKQ0KYGBgDQoNCiMjIE1vbnRobHkgU3BlbmRpbmcgQ2F0ZWdvcnkgQnJlYWtkb3duDQoNClRoZSBuZXh0IHZpc3VhbGl6YXRpb24gZ2l2ZXMgYSBicmVha2Rvd24gb2Ygd2hhdCBjYXRlZ29yaWVzIEkgc3BlbnQgbW9uZXkgaW4gb3ZlciB0aGUgcGFzdCAxNSBtb250aHMuICBUaGlzIGFsbG93cyBtZSB0byBpZGVudGlmeSBhbnkgYXR5cGljYWwgc3BlbmRpbmcgaGFiaXRzIGFuZCBzZWUgd2hhdCBjYXRlZ29yaWVzIG15IG1vbmV5IGhhcyBiZWVuIGdvaW5nIHRvLg0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLndpZHRoPTksIGVjaG89RkFMU0V9DQpkZjMgPC0gZGYgJT4lDQogIGdyb3VwX2J5KEJ1ZGdldCxZZWFyTW9uLFllYXIsTW9udGgpICU+JQ0KICBzdW1tYXJpemUoIkFtb3VudCIgPSBzdW0oQW1vdW50KSwgLmdyb3VwcyA9ICJkcm9wX2xhc3QiKSAlPiUNCiAgdW5ncm91cCgpICU+JQ0KICBmaWx0ZXIoWWVhck1vbiA+IHJlcG9ydF9tb250aCAtIDE1LzEyKQ0KDQpwbG90X2x5KGRmMywNCiAgICAgICAgeCA9IH5hcy5mYWN0b3IoWWVhck1vbiksDQogICAgICAgIHkgPSB+QW1vdW50LA0KICAgICAgICBjb2xvciA9IH5yZW9yZGVyKEJ1ZGdldCwgLUFtb3VudCksDQogICAgICAgIHR5cGUgPSAiYmFyIiwNCiAgICAgICAgbWFya2VyID0gbGlzdChsaW5lID0gbGlzdCh3aWR0aCA9IDEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICdyZ2IoMCwgMCwgMCknKSksDQogICAgICAgIGhvdmVyaW5mbyA9ICJ0ZXh0IiwNCiAgICAgICAgaG92ZXJ0ZXh0ID0gcGFzdGUwKCJBbW91bnQ6ICQiLCBhY2NvdW50aW5nKGRmMyRBbW91bnQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxicj5CdWRnZXQ6ICIsIGRmMyRCdWRnZXQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAiPGJyPk1vbnRoL1llYXI6ICIsIGRmMyRZZWFyTW9uDQogICAgICAgICAgICAgICAgICAgICAgICAgICApDQogICAgICAgICkgJT4lDQogIA0KICBsYXlvdXQodGl0bGUgPSAiTW9udGhseSBTcGVuZGluZyBCcmVha2Rvd24gKFJ1bm5pbmcgMTUgTW9udGhzKSIsDQogICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiQW1vdW50ICgkKSIpLA0KICAgICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIk1vbnRoIiksDQogICAgICAgICBiYXJtb2RlID0gJ3N0YWNrJykNCg0KYGBgDQoNCiMjIFNwZW5kaW5nIFllYXIgVG8gTW9udGggQ29tcGFyaW9ucw0KDQpTaW5jZSB0YWtpbmcgc25hcHNob3RzIG9mIGluZGl2aWR1YWwgbW9udGhzIGNhbiBnaXZlIGhpZ2ggYW1vdW50cyBvZiB2YXJpYWJpbGl0eSB3aXRoIHNtYWxsZXIgc3ViY2F0ZWdvcmllcyAobGlrZSBtdXNpYywgdGF4ZXMsIGFuZCBnaWZ0cyksIHRoZSBuZXh0IHZpc3VhbGl6YXRpb24gaXMgaW50ZW5kZWQgdG8gYWdncmVnYXRlIHRob3NlIG51bWJlciBvdmVyIHNpbWlsYXIgdGltZSBmcmFtZXMgdG8gZ2l2ZSBtb3JlIG1lYW5pbmdmdWwgY29tcGFyaXNvbnMuICBTaW5jZSB0aGlzIGFuYWx5c2lzIHJ1bnMgdGhyb3VnaCBBdWd1c3QsIHRoZSBncmFwaHMgYmVsb3cgYWRkIHVwIGFsbCB0aGUgc3BlbmRpbmcgZnJvbSBKYW51YXJ5IHRocm91Z2ggQXVndXN0IG9mIDIwMTksIDIwMjAsIGFuZCAyMDIxIGFuZCBjb21wYXJlIHRoZW0gdG8gc2VlIGlmIEknbSBzcGVuZGluZyBtb3JlIGluIGEgY2VydGFpbiBjYXRlZ29yeSBmcm9tIGEgc2ltaWxhciB0aW1lIGZyYW1lIGluIHRoZSBwYXN0Lg0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLndpZHRoPTksIGVjaG89RkFMU0V9DQpkZjUgPC0gZGYgJT4lDQogIGZpbHRlcihNb250aC5OdW1iZXIgPD0gbW9udGgocmVwb3J0X21vbnRoKSkgJT4lDQogIGdyb3VwX2J5KFllYXIsQnVkZ2V0KSAlPiUNCiAgc3VtbWFyaXplKEFtb3VudCA9IHN1bShBbW91bnQpLCAuZ3JvdXBzID0gImRyb3BfbGFzdCIpICU+JQ0KICBmaWx0ZXIoIShCdWRnZXQgPT0gIkxpdmluZyIpICYgIShCdWRnZXQgPT0gIlVuY2F0ZWdvcml6ZWQiKSkgJT4lDQogIHVuZ3JvdXAoKSAlPiUNCiAgcmVuYW1lKCJBbW91bnQuTnVtIiA9ICJBbW91bnQiKSAlPiUNCiAgbXV0YXRlKCJBbW91bnQiID0gcGFzdGUwKCIkIixhY2NvdW50aW5nKEFtb3VudC5OdW0pKSkNCg0KDQpwIDwtIGdncGxvdChkYXRhID0gZGY1LCBtYXBwaW5nID0gYWVzKHggPSBZZWFyLCB5ID0gQW1vdW50Lk51bSwgZmlsbCA9IFllYXIsIGxhYmVsID0gQW1vdW50LCBsYWJlbDIgPSBCdWRnZXQpKSArDQogIGdlb21fY29sKGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDAuNSkgKw0KICBnZ3RpdGxlKHBhc3RlMCgiQnVkZ2V0IFllYXIgVG8gTW9udGggQ29tcGFyaXNvbiBUaHJvdWdoICIsIG1vbnRoKHJlcG9ydF9tb250aCwgbGFiZWwgPSBUUlVFLCBhYmJyID0gRkFMU0UpKSkgKw0KICB5bGFiKCJBbW91bnQgKCQpIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpKSArDQogIGZhY2V0X3dyYXAofkJ1ZGdldCkNCg0KI01vdmUgTWFyZ2lucyBmb3IgWSBsYWJlbCBhbmQgYWRkIHRpdGxlDQpncCA8LSBnZ3Bsb3RseShwLCB0b29sdGlwID0gYygiQW1vdW50IiwiQnVkZ2V0IiwieCIpKSU+JQ0KICBsYXlvdXQodGl0bGUgPSBwYXN0ZTAoIlNwZW5kaW5nIFllYXIgVG8gTW9udGggQ29tcGFyaXNvbiBUaHJvdWdoICIsIG1vbnRoKHJlcG9ydF9tb250aCwgbGFiZWwgPSBUUlVFLCBhYmJyID0gRkFMU0UpKSwNCiAgICAgICAgIG1hcmdpbiA9IGxpc3QobCA9IDc1KSkNCg0KI01vdmUgWSBsYWJlbCBzaW5jZSBhbGwgdGV4dCBpcyBzdG9yZWQgYXMgYW5ub3RhdGlvbnMNCmdwW1sneCddXVtbJ2xheW91dCddXVtbJ2Fubm90YXRpb25zJ11dW1sxXV1bWyd4J11dIDwtIC0wLjA3DQoNCmdwDQpgYGANCg0KIyMgU3ViY2F0ZWdvcnkgQnVkZ2V0IE1vbml0b3JpbmcNCg0KQXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgeWVhciwgSSB0eXBpY2FsbHkgY3JlYXRlIGEgYnVkZ2V0IGZvciBzb21lIG9mIG15IGhpZ2ggc3BlbmRpbmcgc3ViY2F0ZWdvcmllcy4gIFRoaXMgYWxsb3dzIG1lIHRvIGdhaW4gYSBiZXR0ZXIgdW5kZXJzdGFuZGluZyBvZiB3aGVyZSBteSBzcGVuZGluZyBoYWJpdHMgYXJlIGluIGNvbXBhcmlzb24gdG8gbXkgc3BlbmRpbmcgZ29hbHMuDQoNCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcud2lkdGg9OSwgZWNobz1GQUxTRX0NCiNTdWIgQnVkZ2V0IFRyYWNrZXINCnN1YmJ1ZGdldHMgPC0gdGliYmxlKCJDYXRlZ29yeSIgPSBjKCJDYXIiLCAiTXVzaWMiLCAiTGVpc3VyZSIsICJIZWFsdGhjYXJlIiksDQogICAgICAgICAgICAgICAgICAgICAiQnVkZ2V0X0Ftb3VudCIgPSBjKDIwMDAsMTIwMCwxNTAwLDEwMDApKQ0KDQpkZjQgPC0gZGYgJT4lDQogIGZpbHRlcihZZWFyID09IG1heChhcy5udW1lcmljKGFzLmNoYXJhY3RlcihkZiRZZWFyKSkpKSAlPiUNCiAgZ3JvdXBfYnkoQnVkZ2V0KSAlPiUNCiAgc3VtbWFyaXplKCJBbW91bnQiID0gc3VtKEFtb3VudCkpICU+JQ0KICBpbm5lcl9qb2luKHN1YmJ1ZGdldHMsIGJ5ID0gYygiQnVkZ2V0IiA9ICJDYXRlZ29yeSIpKQ0KDQpwbG90X2x5KGRhdGEgPSBkZjQpICU+JQ0KICANCiAgICBhZGRfYmFycyh4ID0gfkJ1ZGdldCwNCiAgICAgICAgIHkgPSB+QnVkZ2V0X0Ftb3VudCwNCiAgICAgICAgIHR5cGUgPSAiYmFyIiwNCiAgICAgICAgIHRleHQgPSBwYXN0ZTAoIiQiLGFzLmNoYXJhY3RlcihhY2NvdW50aW5nKGRmNCRCdWRnZXRfQW1vdW50KSkpLA0KICAgICAgICAgdGV4dGZvbnQgPSBsaXN0KGNvbG9yID0gJyMwMDAwMDAnKSwNCiAgICAgICAgIHRleHRwb3NpdGlvbiA9ICJhdXRvIiwgDQogICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gIiNiYWZmY2QiLA0KICAgICAgICAgICAgICAgICAgICAgICBsaW5lID0gbGlzdCh3aWR0aCA9IDEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICdyZ2IoMCwgMCwgMCknKSksDQogICAgICAgICBob3ZlcmluZm8gPSAidGV4dCIsICNUaGlzIHN0b3BzIHRoZSBkZWZhdWx0IGhvdmVyIG92ZXINCiAgICAgICAgIGhvdmVydGV4dCA9IHBhc3RlMCgiQnVkZ2V0ZWQgQW1vdW50OiAkIiwgYWNjb3VudGluZyhkZjQkQnVkZ2V0X0Ftb3VudCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxicj5CdWRnZXQ6ICIsIGRmNCRCdWRnZXQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxicj5DYXRlZ29yeTogUGxhbm5lZCBBbW91bnQiKQ0KICAgICAgICAgKSAlPiUNCiAgDQogIGFkZF9iYXJzKHggPSB+QnVkZ2V0LA0KICAgICAgICAgeSA9IH5BbW91bnQsDQogICAgICAgICB0eXBlID0gImJhciIsDQogICAgICAgICB0ZXh0ID0gcGFzdGUwKCIkIixhcy5jaGFyYWN0ZXIoYWNjb3VudGluZyhkZjQkQW1vdW50KSkpLA0KICAgICAgICAgdGV4dGZvbnQgPSBsaXN0KGNvbG9yID0gJyMwMDAwMDAnKSwNCiAgICAgICAgIHRleHRwb3NpdGlvbiA9ICJhdXRvIiwgDQogICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gIiMyYmM0MzUiLA0KICAgICAgICAgICAgICAgICAgICAgICBsaW5lID0gbGlzdCh3aWR0aCA9IDEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICdyZ2IoMCwgMCwgMCknKSksDQogICAgICAgICBob3ZlcmluZm8gPSAidGV4dCIsICNUaGlzIHN0b3BzIHRoZSBkZWZhdWx0IGhvdmVyIG92ZXINCiAgICAgICAgIGhvdmVydGV4dCA9IHBhc3RlMCgiQW1vdW50OiAkIiwgYWNjb3VudGluZyhkZjQkQW1vdW50KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGJyPkJ1ZGdldDogIiwgZGY0JEJ1ZGdldCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGJyPkNhdGVnb3J5OiBBY3R1YWwgU3BlbmRpbmciKQ0KICAgICAgICAgKSAlPiUNCiAgDQogICBsYXlvdXQoYmFybW9kZSA9ICdvdmVybGF5JywNCiAgICAgICAgdGl0bGUgPSAiWWVhcmx5IFN1YmJ1ZGdldCBUcmFja2luZyIsDQogICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJZZWFybHkgU3BlbmRpbmcgKCQpIiksDQogICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJCdWRnZXQiKSwNCiAgICAgICAgc2hvd2xlZ2VuZCA9IEZBTFNFKQ0KYGBgDQoNCiMjIFV0aWxpdGllcw0KU2luY2UgdXRpbGl0aWVzIHR5cGljYWxseSBoYXZlIHNvbWUgcHJlZGljdGFiaWxpdHkgdG8gdGhlbSwgSSBsaWtlIHRvIHByZWZvcm0gYSB5ZWFyIG92ZXIgeWVhciBtb250aCBjb21wYXJpc29uLiAgSSBzdGFydCB3aXRoIGVsZWN0cmljLCB3aGljaCBpcyBzZWFzb25hbCBzaW5jZSBteSBBL0MgYW5kIGhlYXQgYXJlIGJvdGggZWxlY3RyaWMuICBJbiBhZGRpdGlvbiwgSSBwZXJmb3JtZWQgYSBsaW5lYXIgcmVncmVzc2lvbiB0byBtYWtlIGEgcHJlZGljdGlvbiBmb3Igd2hhdCBteSBlbGVjdHJpYyBzaG91bGQgYmUgZm9yIGVhY2ggbW9udGggdXNpbmcgcHJldmlvdXMgeWVhcidzIGNvc3RzIHRvIHNlZSBob3cgbXVjaCB0aGUgYWN0dWFsIGNvc3QgdmFyaWVzIGZyb20gdGhhdC4NCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy53aWR0aD05LCBlY2hvPUZBTFNFfQ0KI0NyZWF0ZSBuZXcgZGF0YSBmcmFtZSBmb3IgZWxlY3RyaWMNCmRmX2VsZWN0cmljIDwtIGRmW2dyZXBsKCJFTEVDVFJJQyIsZGYkRGVzY3JpcHRpb24sZml4ZWQgPSBUUlVFKSwgXQ0KDQojQ3JlYXRlIGEgcHJlZGljdGlvbiB1c2luZyBsZWFzdCBzcXVhcmVzIG1ldGhvZCB0bw0KbW9kX2VsZWN0cmljIDwtIGxtKEFtb3VudCB+IE1vbnRoLCBkYXRhID0gZGZfZWxlY3RyaWMpDQoNCmdyaWQgPC0gZGZfZWxlY3RyaWMgJT4lDQogIGRhdGFfZ3JpZChNb250aCkgJT4lDQogIGFkZF9wcmVkaWN0aW9ucyhtb2RfZWxlY3RyaWMsICJBbW91bnQiKQ0KDQojR3JhcGgNCnBsb3RfbHkoZGF0YSA9IGRmX2VsZWN0cmljLA0KICAgICAgICB4ID0gfk1vbnRoKSAlPiUNCiAgYWRkX3RyYWNlKHkgPSB+QW1vdW50LA0KICAgICAgICBjb2xvciA9IH5ZZWFyLA0KICAgICAgICB0eXBlID0gInNjYXR0ZXIiLA0KICAgICAgICBtb2RlID0gImxpbmUrbWFya2VyIiwNCiAgICAgICAgaG92ZXJpbmZvID0gInRleHQiLA0KICAgICAgICBob3ZlcnRleHQgPSBwYXN0ZTAoIkFtb3VudDogJCIsIGFjY291bnRpbmcoZGZfZWxlY3RyaWMkQW1vdW50KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICI8YnI+TW9udGgvWWVhcjogIiwgZGZfZWxlY3RyaWMkWWVhck1vbikNCiAgICAgICAgKSU+JSANCiAgYWRkX21hcmtlcnMoZGF0YSA9IGdyaWQsDQogICAgICAgICAgICB4ID0gfk1vbnRoLA0KICAgICAgICAgICAgeSA9IH5BbW91bnQsDQogICAgICAgICAgICBuYW1lID0gIlByZWRpY3Rpb24iLA0KICAgICAgICAgICAgdHlwZSA9ICJzY2F0dGVyIiwNCiAgICAgICAgICAgIG1hcmtlciA9IGxpc3QoY29sb3I9J3JlZCcsIHNpemUgPSAxMCksDQogICAgICAgICAgICBob3ZlcmluZm8gPSAidGV4dCIsDQogICAgICAgICAgICBob3ZlcnRleHQgPSBwYXN0ZTAoIkFtb3VudDogJCIsIGFjY291bnRpbmcoZ3JpZCRBbW91bnQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxicj5Nb250aCBQcmVkaWN0ZWQ6ICIsIGdyaWQkTW9udGgpDQogICAgICAgICAgICApICU+JQ0KICANCiAgbGF5b3V0KHRpdGxlID0gIkVsZWN0cmljIENvc3QgQW5sYXlzaXMiLA0KICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIkFtb3VudCAoJCkiKSwNCiAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJNb250aCIpKQ0KDQoNCmBgYA0KDQpGb3Igd2F0ZXIgYW5kIHNld2FnZSwgdGhlc2UgdHdvIGFyZSB0eXBpY2FsbHkgdGllZCB0b2dldGhlciBhbmQgSSBoYXZlIGdyYXBoZWQgdGhlbSBzaWRlIGJ5IHNpZGUgYmVsb3cuIEZvciBzZXdhZ2UsIHRoZXkgZml4IHRoZSBwcmljZSBieSAxMDAwIGdhbGxvbnMgYW5kIGl0IHR5cGljYWxseSBmYWxscyBiZXR3ZWVuIDEwMDAgYW5kIDIwMDAgc28gdGhleSBjaGFyZ2UgbWUgZm9yIDEgb3IgMiAiVW5pdHMiIG9mIHNld2FnZSwgd2hpY2ggaXMgd2h5IHRoZSBncmFwaCBpcyBzbyBzdGVwIG9yaWVudGVkLg0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLndpZHRoPTksIGVjaG89RkFMU0V9DQojRmFjZXQgb3RoZXIgdXRpbGl0eSBjb3N0cyB0aGF0IGFyZSBtb3JlIGZpeGVkIChXYXRlciBhbmQgU2V3YWdlKQ0KDQpXYXRlciA8LSBmaWx0ZXIoZGYsIHN0cl9kZXRlY3QoRGVzY3JpcHRpb24sICJXQVRFUiIpKQ0KU2V3YWdlIDwtIGZpbHRlcihkZiwgc3RyX2RldGVjdChEZXNjcmlwdGlvbiwgIlNFV0FHRSIpKQ0KDQpwX3dhdGVyIDwtIHBsb3RfbHkoZGF0YSA9IFdhdGVyLA0KICAgICAgIHggPSB+TW9udGgsDQogICAgICAgeSA9IH5BbW91bnQsDQogICAgICAgY29sb3IgPSB+WWVhciwNCiAgICAgICB0eXBlID0gInNjYXR0ZXIiLA0KICAgICAgIG1vZGUgPSAibGluZXMrbWFya2VycyIsDQogICAgICAgaG92ZXJpbmZvID0gInRleHQiLA0KICAgICAgIGhvdmVydGV4dCA9IHBhc3RlMCgiQW1vdW50OiAkIiwgYWNjb3VudGluZyhXYXRlciRBbW91bnQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiPGJyPk1vbnRoL1llYXI6ICIsIFdhdGVyJFllYXJNb24pLA0KICAgICAgIGxlZ2VuZGdyb3VwID0gflllYXIpDQoNCnBfc2V3YWdlIDwtIHBsb3RfbHkoZGF0YSA9IFNld2FnZSwNCiAgICAgICB4ID0gfk1vbnRoLA0KICAgICAgIHkgPSB+QW1vdW50LA0KICAgICAgIGNvbG9yID0gflllYXIsDQogICAgICAgdHlwZSA9ICJzY2F0dGVyIiwNCiAgICAgICBtb2RlID0gImxpbmVzK21hcmtlcnMiLA0KICAgICAgIHNob3dsZWdlbmQgPSBGLA0KICAgICAgIGhvdmVyaW5mbyA9ICJ0ZXh0IiwNCiAgICAgICBob3ZlcnRleHQgPSBwYXN0ZTAoIkFtb3VudDogJCIsIGFjY291bnRpbmcoU2V3YWdlJEFtb3VudCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICI8YnI+TW9udGgvWWVhcjogIiwgU2V3YWdlJFllYXJNb24pLA0KICAgICAgIGxlZ2VuZGdyb3VwID0gflllYXIpDQoNCnN1YnBsb3QocF93YXRlcixwX3Nld2FnZSkgJT4lDQogIA0KICBsYXlvdXQoeWF4aXMgPSBsaXN0KHRpdGxlID0gIkFtb3VudCAoJCkiKSwNCiAgICAgICAgIGFubm90YXRpb25zID0gbGlzdCgNCiAgICAgICAgIGxpc3QoeCA9IDAuMTUgLCB5ID0gMS4wMiwgdGV4dCA9ICJXYXRlciBDb3N0Iiwgc2hvd2Fycm93ID0gRiwgeHJlZj0ncGFwZXInLCB5cmVmPSdwYXBlcicsIGZvbnQgPSBsaXN0KHNpemUgPSAxOCkpLA0KICAgICAgICAgbGlzdCh4ID0gMC44NSAsIHkgPSAxLjAyLCB0ZXh0ID0gIlNld2FnZSBDb3N0Iiwgc2hvd2Fycm93ID0gRiwgeHJlZj0ncGFwZXInLCB5cmVmPSdwYXBlcicsIGZvbnQgPSBsaXN0KHNpemUgPSAxOCkpKQ0KICAgICAgICAgKQ0KYGBg